package org.jetlinks.pro.tenant.web;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.hswebframework.web.authorization.annotation.Authorize;
import org.hswebframework.web.authorization.annotation.Resource;
import org.hswebframework.web.authorization.annotation.SaveAction;
import org.jetlinks.pro.assets.AssetBindManager;
import org.jetlinks.pro.assets.AssetsUtils;
import org.jetlinks.pro.tenant.TenantAssetManager;
import org.jetlinks.pro.tenant.TenantMember;
import org.jetlinks.pro.tenant.impl.BindAssetsRequest;
import org.jetlinks.pro.tenant.impl.UnbindAssetsRequest;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/tenant")
@AllArgsConstructor
@Tag(name = "租户资产管理")
@Resource(id = "tenant-manager", name = "租户管理-管理端")
public class TenantAssetsController {

    private final TenantAssetManager assetManager;

    /**
     * 绑定指定租户下的资产
     *
     * @param tenantId    租户ID
     * @param requestFlux 请求
     * @return 绑定数量
     */
    @PostMapping("/{tenantId}/assets/{assetType}/_bind")
    @SaveAction
    @Operation(summary = "绑定资产到指定到租户下")
    public Mono<Integer> bindAssets(@PathVariable @Parameter(description = "租户ID") String tenantId,
                                    @PathVariable @Parameter(description = "资产类型") String assetType,
                                    @RequestBody Flux<BindAssetsRequest> requestFlux) {
        return assetManager
            .bindAssets(tenantId, false, requestFlux.doOnNext(request -> request.setAssetType(assetType)))
            .as(AssetsUtils.setMonoBindSource(AssetBindManager.SOURCE_MANUAL));
    }

    /**
     * 解绑指定租户下的资产
     *
     * @param tenantId    租户ID
     * @param requestFlux 请求
     * @return 解绑数量
     */
    @PostMapping("/{tenantId}/assets/{assetType}/_unbind")
    @SaveAction
    @Operation(summary = "解绑租户资产")
    public Mono<Integer> unbindAssets(@PathVariable @Parameter(description = "租户ID") String tenantId,
                                      @PathVariable @Parameter(description = "资产类型") String assetType,
                                      @RequestBody Flux<UnbindAssetsRequest> requestFlux) {
        return assetManager
            .unbindAssets(tenantId, requestFlux.doOnNext(request -> request.setAssetType(assetType)))
            .as(AssetsUtils.setMonoBindSource(AssetBindManager.SOURCE_MANUAL));
    }


    /**
     * 绑定资产信息
     *
     * @param requestFlux 请求
     * @return 绑定数量
     */
    @PostMapping("/assets/{assetType}/_bind")
    @Authorize(merge = false)
    @Operation(summary = "绑定资产到当前租户")
    public Mono<Integer> bindAssets(@PathVariable @Parameter(description = "资产类型") String assetType,
                                    @RequestBody Flux<BindAssetsRequest> requestFlux) {
        return TenantMember
            .current()
            .flatMap(tenant -> assetManager
                .bindAssets(
                    tenant.getTenant().getId(),
                    true,
                    requestFlux.doOnNext(request -> request.setAssetType(assetType)))
            ).as(AssetsUtils.setMonoBindSource(AssetBindManager.SOURCE_MANUAL));
    }

    /**
     * 解绑资产
     *
     * @param requestFlux 请求
     * @return 解绑数量
     */
    @PostMapping("/assets/{assetType}/_unbind")
    @Authorize(merge = false)
    @Operation(summary = "解绑资产到当前租户")
    public Mono<Integer> unbindAssets(@PathVariable @Parameter(description = "资产类型") String assetType,
                                      @RequestBody Flux<UnbindAssetsRequest> requestFlux) {
        return TenantMember
            .current()
            .flatMap(tenant -> assetManager
                .unbindAssets(tenant.getTenant().getId(), requestFlux
                    .doOnNext(request -> {
                        request.setAssetType(assetType);
                        //不是租户管理员,解绑自己的
                        if (!tenant.isAdmin()) {
                            request.setUserId(tenant.getUserId());
                        }
                    })))
            .as(AssetsUtils.setMonoBindSource(AssetBindManager.SOURCE_MANUAL));
    }


}
